#ifndef _GP_LAYOUT_MAP_H
#define _GP_LAYOUT_MAP_H

#ifdef x86_64
#define LAYOUT_FILE "/home/hcgy/Documents/esm6800h/test/schedule/layout.json"
#else
#define LAYOUT_FILE "/mnt/nandflash/apps/config/layout.json"
#endif

#include <iostream>

typedef enum
{
   DJ_QPCR_48HOLES,
   DJ_QPCR_START = DJ_QPCR_48HOLES,
   DJ_QPCR_BOARDJAW,
   DJ_QPCR_REAGENT,
   DJ_QPCR_BARCODE,
   DJ_QPCR_CLEANPOOL,
   DJ_QPCR_TRANS,
   DJ_QPCR_END = DJ_QPCR_TRANS,

   DJ_PURIFY_8HOLES_A,
   DJ_PURIFY_START = DJ_PURIFY_8HOLES_A,
   DJ_PURIFY_8HOLES_B,
   DJ_PURIFY_SPLIT,
   DJ_PURIFY_REAGENT,
   DJ_PURIFY_BARCODE,
   DJ_PURIFY_MAG_SHAKE,
   DJ_PURIFY_CLEANPOOL,
   DJ_PURIFY_END = DJ_PURIFY_CLEANPOOL,

   DP1_TUBE_JAW,
   DP1_TYPE_START = DP1_TUBE_JAW,
   DP1_TIPS,
   DP1_TIPS_INTER_REF,
   DP1_8HOLES_JAW_A,
   DP1_8HOLES_JAW_B,
   DP1_8HOLES_SPIT_A,
   DP1_8HOLES_SPIT_B,
   DP1_8HOLES_SHAKE_TIP,
   DP1_TUBE8_SHAKE_JAW,
   DP1_8HOLES_SPIT_BUFF,
   DP1_8HOLES_BUFF_JAW,
   DP1_DROPTIP,
   DP1_DROPTUBE,
   DP1_OPENLID_JAW,
   DP1_REAGENT_JAW,
   DP1_MAG_SHAKE_JAW,
   DP1_OPENLID_SUCK,
   DP1_TYPE_END = DP1_OPENLID_SUCK,


   DP8_PCR_TRANS,
   DP8_TYPE_START = DP8_PCR_TRANS,
   DP8_PCR_BUFF_TIP,
   DP8_PCR_BUFF_JAW,
   DP8_PCR_BUFF_TIP_1,
   DP8_DNA_BUFF_JAW,
   DP8_DNA_BUFF_TIP,
   DP8_DNA_BUFF_TIP_1,
   DP8_TIP48_TRANS,//for tip8 trans tips
   DP8_TIP48_PURIFY_A,
   DP8_TIP48_PURIFY_B,
   DP8_TIP48_BUFF,//for tip1 trans tips
   DP8_REAGENT,
   DP8_TUBE8_SHAKE,
   DP8_DROPTIP,
   DP8_DROPTIP_1,
   DP8_FILM_SRC,
   DP8_HEAT_SEAL,
   DP8_SCANCODE,   
   DP8_WASTE_LIQUID,
   DP8_TYPE_END = DP8_WASTE_LIQUID,

   SEAL_X_WAIT,
   SEAL_TYPE_START = SEAL_X_WAIT,
   SEAL_X_WORK,
   SEAL_Z_WAIT,
   SEAL_Z_WORK,
   SEAL_TYPE_END = SEAL_Z_WORK,

   OPENLID_X_SUCK,
   OPENLID_TYPE_START = OPENLID_X_SUCK,
   OPENLID_X_OPEN,
   OPENLID_Z_OPEN,
   OPENLID_Z_WAIT,
   OPENLID_TYPE_END = OPENLID_Z_WAIT,

   QPCR1_BATH_X_WAIT,
   QPCR1_TYPE_START = QPCR1_BATH_X_WAIT,
   QPCR1_BATH_X_WORK,
   QPCR1_BATH_Z_WAIT,
   QPCR1_BATH_Z_WORK,
   QPCR1_OPTICS_CHNNEL,
   QPCR1_TYPE_END = QPCR1_OPTICS_CHNNEL,

   QPCR2_BATH_X_WAIT,
   QPCR2_TYPE_START = QPCR2_BATH_X_WAIT,
   QPCR2_BATH_X_WORK,
   QPCR2_BATH_Z_WAIT,
   QPCR2_BATH_Z_WORK,
   QPCR2_OPTICS_CHNNEL,
   QPCR2_TYPE_END = QPCR2_OPTICS_CHNNEL,

   LOG1_PCR_BOARD,
   LOG_START_PURIFY = LOG1_PCR_BOARD,
   LOG1_DOWN,
   LOG1_EXCHANGE12,
   LOG2_EXCHANGE12,
   LOG2_EXCHANGE_BEFORE,
   LOG2_EXCHANGE_AFTER,
   LOG2_EXCHANGE23,
   LOG_STOP_PURIFY = LOG2_EXCHANGE23,
   LOG3_UP,
   LOG_START_QPCR = LOG3_UP,
   LOG3_QPCR_GET,//for log3 jawz and jaw x
   LOG3_QPCR_DROP,//for log3 jawz and jaw x
   LOG3_BATH1,//
   LOG3_BATH2,//
   LOG_STOP_QPCR = LOG3_BATH2,
}en_layout_type;

#define MAX_NUM_LOG_LOCS (LOG_STOP_QPCR-LOG_START_PURIFY+1)

// #define DP1_TYPE_START DP1_TUBE_JAW
// #define DP1_TYPE_END DP1_OPENLID_SUCK

// #define DP8_TYPE_START DP8_TIPS
// #define DP8_TYPE_END DP8_TIPS


typedef enum
{
    MODULE_DJ_QPCR,
    MODULE_DJ_PURIFY,
    MODULE_DP1,
    MODULE_DP8,
    MODULE_SEAL,
    MODULE_SHAKE,
    MODULE_OPENLID,
    MODULE_QPCR1,
    MODULE_QPCR2,
    MODULE_SCANCODE,
    MODULE_DRAWER,
    MODULE_COOL,
    MODULE_DP8_1,
    MODULE_LOGISTIC,
    MODULE_MAX_NUM,
}en_module_type;

typedef struct _location_layout
{
    unsigned short location_type;
    unsigned short indexX;//external index
    unsigned short indexY;
    int column_x;//index in a module
    int row_y;

}location_layout;

typedef struct _location_axis
{
    unsigned int x;
    unsigned int y;
    unsigned int z;

}location_axis;


typedef struct _module_loc
{
    int init_x;
    int init_y;
    float delta_x;
    float delta_y;
    unsigned short max_num_x;
    unsigned short max_num_y;
}module_loc;


typedef struct _multi_module_loc
{
    int locationType;
    float delta_module_x;
    float delta_module_y;
    unsigned short max_num_module_x;
    unsigned short max_num_module_y;
    module_loc firstModuleLoc;
}multi_module_loc;

void print_multi_module_loc(multi_module_loc * locToPrint);

typedef enum
{
    I_PURIFY_DJ_PROTAINASE = 1,
    I_PURIFY_DJ_MAGNET = 2,
    I_PURIFY_DJ_HELPDOWN = 0,
    I_PURIFY_DJ_INTERNEL_REF = 3,
}en_purify_dj_reagent_index;

typedef enum
{
    I_PURIFY_DP8_WASHOFF = 0,
    I_PURIFY_DP8_CLEAN1 = 1,
    I_PURIFY_DP8_CLEAN2 = 2,
    I_PURIFY_DP8_CLEAN3 = 3,
}en_purify_dp8_reagent_index;

typedef struct _locs_seal
{
    int x_wait;
    int x_work;
    int z_wait;
    int z_work;
}locs_seal;

typedef enum {
  OPTICS_CHANNEL1_CY5 = 4,
  OPTICS_CHANNEL2_ROX = 3,
  OPTICS_CHANNEL3_TAMRA = 2,
  OPTICS_CHANNEL4_HEX = 1,
  OPTICS_CHANNEL5_FAM = 0,
  OPTICS_CHANNEL_MAX = 5,
}en_optics_chan;

typedef struct _locs_qpcr
{
    int id;
    int bath_x_wait;
    int bath_x_work;
    int bath_z_wait;
    int bath_z_work;
    int chanPos[OPTICS_CHANNEL_MAX];   
}locs_qpcr;

typedef struct _dynamic_z
{
    int z_tube_mouth;
    int z_max;
}dynamic_z;

typedef enum
{
    Z_LOC_DP1_OPENLID_JAW,
    Z_LOC_DP1_START = Z_LOC_DP1_OPENLID_JAW,
    Z_LOC_DP1_OPENLID_TIP,
    Z_LOC_DP1_SAMPLE_JAW,
    Z_LOC_DP1_TUBE8_JAW,//tube8 on shelf
    Z_LOC_DP1_TUBE8_BUFF_JAW,
    Z_LOC_DP1_TUBE8_BUFF_TIP,
    Z_LOC_DP1_TUBE8_SHAKE_JAW,
    Z_LOC_DP1_GET_TIP,
    Z_LOC_DP1_GET_TIP_INTER_REF,
    Z_LOC_DP1_DROP_TUBE8_JAW,
    Z_LOC_DP1_REAGENT_JAW,
	Z_LOC_DP1_MAG_SHAKE_JAW,
    Z_LOC_DP1_DROP_TIP,    
    Z_LOC_DP1_END = Z_LOC_DP1_DROP_TIP,
    Z_LOC_DJP_REAGENT,
    Z_LOC_DJP_START=Z_LOC_DJP_REAGENT,
    Z_LOC_DJP_TUBE8,
    Z_LOC_DJP_MAG_SHAKE,
    Z_LOC_DJP_CLEAN,
    Z_LOC_DJP_END=Z_LOC_DJP_CLEAN,
    Z_LOC_DJQ_REAGENT,
    Z_LOC_DJQ_START=Z_LOC_DJQ_REAGENT,
    Z_LOC_DJQ_48HOLES,
    Z_LOC_DJQ_BOARDJAW,
    Z_LOC_DJQ_TRANSJAW,
    Z_LOC_DJQ_CLEAN,
    Z_LOC_DJQ_END=Z_LOC_DJQ_CLEAN,
    Z_LOC_DP8_GET_TIP,
    Z_LOC_DP8_START = Z_LOC_DP8_GET_TIP,
    Z_LOC_DP8_GET_TIP_1,    
    Z_LOC_DP8_DROP_TIP,
    Z_LOC_DP8_DROP_TIP_1,
    Z_LOC_DP8_DROP_TIP_DROP,
    Z_LOC_DP8_REAGENT, 
    Z_LOC_DP8_TUBE8,
    Z_LOC_DP8_DNA_BUFF,
    Z_LOC_DP8_DNA_BUFF_1,
    Z_LOC_DP8_SUCK_PUMP,
    Z_LOC_DP8_TRANS_JAW,
    Z_LOC_DP8_DNA_BUFF_JAW,
    Z_LOC_DP8_PCR_BUFF_JAW,
    Z_LOC_DP8_SEAL_JAW,
    Z_LOC_DP8_FILM_JAW,
    Z_LOC_DP8_DROP_LIQUID,
    Z_LOC_DP8_PCR_BUFF,
    Z_LOC_DP8_PCR_BUFF_1,
    Z_LOC_DP8_END = Z_LOC_DP8_PCR_BUFF_1,

    Z_LOC_MAX_NUM
}en_z_loc;

int convertToZLocType(int locTypeIn);

typedef struct _logistic_loc
{
    int x_y_base;//x or y
    int z_change;// z or x change
}logistic_loc;

class CGpLayout
{

public:
    static CGpLayout* get_instance(void);
    int convertToAxisLoc(const location_layout * pstLayoutIn,location_axis * pstLocAxisOut);
    virtual ~CGpLayout();

    int getZloc(int zlocTypeIn,dynamic_z * zlocOut);

    int getZloc_withoutConvert(int zlocTypeIn,dynamic_z * zlocOut);

    locs_seal * getOpenlidPos(void);

    locs_seal * getSealPos(void);

    int getQpcrOpticalPos(int QpcrId,int channelId);

    locs_qpcr * getQpcrPos(int QpcrId);

    int getLogisticLoc(int logLocTypeIn, logistic_loc * logLocOut);

private:
    static CGpLayout * m_pInstance;

    CGpLayout(){};
    CGpLayout(const CGpLayout & ){};
    CGpLayout & operator = (const CGpLayout & ){};
    CGpLayout(const char * fileIn);

    class CGarbo     
    {    
    public:    
        ~CGarbo()    
        {    
            if(CGpLayout::m_pInstance)    
                delete CGpLayout::m_pInstance; 

            std::cout<<"~CGarbo"<<std::endl;   
        }    
    };
        
    static CGarbo Garbo; 

    multi_module_loc * m_dp1_locations;
    int m_numDp1Locs;
    multi_module_loc * m_dp8_locations;
    int m_numDp8Locs;

    multi_module_loc * m_dj_pu_locations;
    int m_numDjpLocs;

    multi_module_loc * m_dj_qpcr_locations;
    int m_numDjqLocs;


    locs_seal * m_pstSealLocs;

    locs_qpcr * m_pstQpcrLocs;
    int m_numQpcr;

    locs_seal * m_pstOpenlidLocs;

    dynamic_z * m_z_locsArr;


    logistic_loc * m_pstLogLocs;

    int load_layout(const char * fileIn);    

    int get_module_type(int locTypeIn);

    int isParamValid(const location_layout * pstLayoutIn, const multi_module_loc * ptrLocModules);

};

typedef enum
{
    AREA_PCR_REAGENT_PRE,
    AREA_PURIFY_REAGENT_PRE_A,
    AREA_PURIFY_REAGENT_PRE_B,
    AREA_HEAT_SHAKE,
    AREA_SYSTEM_SETUP,    
}en_area_divide;

typedef struct _loc_base
{
    int areaId;
    int indexX_column;
    int indexY_row;
}loc_base;

#define WASTE_DOOR_CLOSE_POS 325000


typedef enum
{
    EN_WASTE_DOOR_DROPTIP1,
    EN_WASTE_DOOR_DROPTIP8,
    EN_WASTE_DOOR_DROPTIP8_1,
    EN_WASTE_DOOR_TUBE8,
    EN_WASTE_DOOR_BOARD48,
    EN_WASTE_DOOR_WASTE_LIQUID,
    EN_WASTE_DOOR_CLOSE,
    EN_WASTE_MAX_POS_NUM,
}en_door_pos;

typedef struct _door_move
{
    int doorPos;
    int result;
}door_move;

void * thread_open_waste_door(void * paramIn);

#define SID_WASTE_DOOR 42

typedef enum
{
    SUB_MODULE_LOG1,
    SUB_MODULE_LOG2,
    SUB_MODULE_LOG3,
}en_log_sub_module;

#endif
